from twisted.internet import reactor, protocol, task
from ProtocolDefine import GameDefineProtocol
from TienLenUtils import *
from threading import Thread
import time

class CardGameProtocol(protocol.Protocol):
    authenticated = False
    lastreceived = 0
    Username = None
    Status = None
    CurrentRoom = None
    PlayingStatus = None
    userhandle = None
    RequestList = []
    ResponseList = []
     
    def connectionMade(self):
        print self.transport.client
        self.userhandle = PlayerCardGame(self)
        self.factory.addConnection(self)
       
    def connectionLost(self,reason):
        if self.userhandle.authenticated:
            self.factory.userQuit(self.userhandle.username)
        self.factory.removeConnection(self)        
        print "Lost connection ....",self.transport.client 
        
    def dataReceived(self, data):
        self.userhandle.processData(data)
        self.lastreceived = time.time()        
        
    def response(self,data):
        #self.ResponseList.append(data)
        self.transport.write(data)
        self.transport.write("\n")
        

class CardGameFactory(protocol.ServerFactory):

    bCheckIdle = True
    IDLE_TIME = 30000
    protocol = CardGameProtocol
    RoomList = dict()
    RoomIndex = []
    UserList = []
    UserStatusList = []
    Connections = []
    
    def addConnection(self,p):
        self.Connections.append(p)
    
    def removeConnection(self,p):
        self.Connections.remove(p)
    
    def addUser(self,user):
        try:
            bfound = self.UserList.index(user)
        except:
            bfound = -1
        if bfound == -1:
            self.UserList.append(user)
            self.UserStatusList.append(None)
            #print user," has been added."
            return True            
        else:
            return False
            
    def createRoom(self,user,protocol,betmoney,password=None):
        
        #check betmoney input
        try:
            ibetmoney = int(betmoney)
        except:
            return False
        
        try:
            i = self.UserList.index(user)            
        except:
            i = -1            
        if i <> -1:
            if not self.UserStatusList[i]:
                #room = AGame(betmoney=ibetmoney,password=password)
                room = XiangqiGame(betmoney=ibetmoney,password=password)
                room.join(user,protocol,password)
                self.RoomList[user]=room
                self.RoomIndex.append(room)
                self.UserStatusList[i] = "hosting"
                room.start()
                return True
            else:
                return False
        else:
            return False
    
    def partRoom(self,user):
        try:
            i = self.UserList.index(user)            
        except:
            i = -1            
        if i <> -1:
            if self.RoomList.has_key(user):
                if self.RoomList[user].part(user):
                    del self.RoomList[user]
                else:
                    return False
            self.UserStatusList[i] = None
            for j in range(len(self.RoomIndex)):
                if self.RoomIndex[j].running == False:
                    del self.RoomIndex[j]            
        else:
            return False
        return True
        
    def joinRoom(self,user,hostname,protocol,password=None):
        if self.RoomList.has_key(hostname):
            i = self.getUserIndex(user)
            if i <> -1 and user <> hostname:
                if self.RoomList[hostname].join(user=user,protocol=protocol,password=password):
                    self.RoomList[user] = self.RoomList[hostname]
                    self.UserStatusList[i] = "joining"
                else:
                    return False
                if len(self.RoomList[hostname].userlist)==2:
                    self.RoomList[hostname].pcstartGame();
        else:
            return False
        return True
    
    def listRoom(self,protocol):
        notify = GameDefineProtocol.GameNotify()
        strlist = ""
        for room in self.RoomIndex:
            if room.password:
                p = 1
            else:
                p = 0
            strlist = strlist + room.host + " " +str(room.betmoney)+ " " + str(p)+" "
        strlist = strlist.strip()
        protocol.response(notify.NOTIFY_ROOM_LIST+" "+strlist)
    
    def addGameRequest(self,request):
        user,data = request
        if self.RoomList.has_key(user):
            self.RoomList[user].addRequest(request)
            
    def userQuit(self,user):
        try:
            i = self.UserList.index(user)
        except:
            i = -1
        if i <> -1:
            if self.UserStatusList[i]:
                self.partRoom(user)
            del self.UserList[i]
            del self.UserStatusList[i]
            
#    def getUserStatus(self,user):
#        try:
#            i = self.UserList.index(user)
#        except:
#            i = -1
#        if i <> -1:
#            return self.UserStatusList[i]
#        else:
#            raise "Not found user"
#
#    def getUserRoom(self,user):
#        try:
#            i = self.UserList.index(user)
#        except:
#            i = -1
#        if i <> -1:
#            return self.UserRoomList[i]
#        else:
#            raise "Not found user"
#    
    def getUserIndex(self,user):
        try:
            i = self.UserList.index(user)            
        except:
            i = -1            
        return i
    
    def cleanConnections(self):            
        for p in self.Connections:
            #print p.lastreceived
            if not p.lastreceived:
                p.lastreceived = time.time()
            curtime = time.time()
            if p.lastreceived>0:
                if curtime - p.lastreceived > self.IDLE_TIME:
                    print "Clean Connections"
                    p.transport.loseConnection()            
            
    def debug(self):
        print "RoomList len "+str(len(self.RoomList))
        print "RoomIndex len "+str(len(self.RoomIndex))
        print "UserList len "+str(len(self.UserList))
        print "Connections len "+str(len(self.Connections))
def main():
    """This runs the protocol on port 8000"""
    factory = CardGameFactory()
    check = task.LoopingCall(factory.cleanConnections)
    check.start(30.0)    
    reactor.listenTCP(8008,factory)
    #reactor.callFromThread(factory.cleanConnections,)
    reactor.run()

# this only runs if the module was *not* imported
if __name__ == '__main__':
    main()
